import java.io.OutputStreamWriter;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * SoDoKuPuzzle
 */
public class SoDoKuPuzzle {

    static final int MAX_SODOKU_SIZE = 9;  // Predefined maximum size of puzzles.


    int     m_puzzleSize;
    int     m_boxSize;
    int[][] m_puzzle;

    // Create a SoDoKu Puzzle of size <puzzleSize> x <puzzleSize> and with
	// interior boxes of size <boxSize> x <boxSize>
	SoDoKuPuzzle( int puzzleSize, int boxSize ) 
	{
		assert( puzzleSize <= MAX_SODOKU_SIZE );
		assert( (puzzleSize % boxSize) == 0 );

        m_puzzleSize = puzzleSize;
        m_boxSize    = boxSize;
        m_puzzle     = new int[MAX_SODOKU_SIZE][MAX_SODOKU_SIZE];

        for ( int col=0 ; col < MAX_SODOKU_SIZE ; ++col ) {
			for ( int row=0 ; row < MAX_SODOKU_SIZE ; ++row ) {
				m_puzzle[col][row] = 0;
			}
		}
	}

	// Set start state of puzzle (e.g. "1....1....1....1"); returns true if setting ok, otherwise false.
	boolean setPuzzle( String str ) {
		if ( str.length() != getNumSquares() ) return false;
		int n = 0;
		for ( int row= m_puzzleSize-1 ; row >= 0 ; --row ) {
			for ( int col=0 ; col < m_puzzleSize ; ++col ) {
				if ( str.charAt(n) == '.' ) {
					clear( col, row );
				}
				else {
					int val = str.charAt(n) - '0';
					if ( !( val>0 && val<= getPuzzleSize() ) ) return false;
					set( col, row, val );
				}
				++n;
			}
		}
		return true;
	}


    // Display puzzle.
	void display( PrintWriter os ) {
        for ( int row= m_puzzleSize-1 ; row >= 0 ; --row ) {
	        for ( int col=0 ; col < m_puzzleSize ; ++col ) {
		        if ( m_puzzle[col][row] == 0 ) {
	        	    os.print( '.' );
			    }
	            else {
			        os.print( (char)(m_puzzle[col][row] + '0') );
		        }
		    }
	        os.print('\n');
	    }
    }

	// Get puzzle size.
	int getPuzzleSize() { return m_puzzleSize; }

	// Get box size.
	int getBoxSize() { return m_boxSize; }

	// Get number of squares
	int getNumSquares() { return m_puzzleSize * m_puzzleSize; }

	// Get value of square
	int getSqr( int col, int row ) {
		assert( col < m_puzzleSize );
		assert( row < m_puzzleSize );
		return m_puzzle[ col ][ row ];
	}

	// Get value of square
	int getSqr( int sq ) {
		assert( sq < getNumSquares() );
		return getSqr( Col(sq), Row(sq) );
	}

	// Assign value to square ( using col,row coordinates.
	void set( int col, int row, int val ) {
		assert( val > 0 && val <= m_puzzleSize );
		assert( col < m_puzzleSize );
		assert( row < m_puzzleSize );
		//assert( m_puzzle[col][row] == 0 );
		m_puzzle[col][row] = val;
	}

	// Assign value to square.
	void set( int sq, int val ) {
		assert( sq < getNumSquares() );
		set( Col(sq), Row(sq), val );
	}

	// Clear square (using col, row coordinates).
	void clear( int col, int row ) {
		assert( col < m_puzzleSize );
		assert( row < m_puzzleSize );
		m_puzzle[col][row] = 0;
	}

	// Clear square.
	void clear( int sq ) {
		assert( sq < getNumSquares() );
		clear( Col(sq), Row(sq) );
	}

	// Given square, return column coordinate.
	int Col( int sq ) { return sq % m_puzzleSize; }

	// Given square, return row coordinate.
	int Row( int sq ) { return sq / m_puzzleSize; }

	// Given col, row coordinates, return square.
	int Sqr( int col, int row ) { return row * m_puzzleSize + col; }

}
